package com.lianjia.crawler.utils;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.lianjia.crawler.model.HouseInfo;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 文件保存工具类，用于保存爬取结果到JSON和CSV文件
 */
public class FileUtils {
    private static final Logger logger = LoggerFactory.getLogger(FileUtils.class);
    private static final ObjectMapper objectMapper = new ObjectMapper();
    
    // 结果保存路径
    private static final String IMAGE_PATH = "result/image";
    private static final String INFORMATION_PATH = "result/information";
    
    /**
     * 保存图片到本地
     *
     * @param imageUrl 图片URL
     * @param cityCode 城市代码
     * @param userAgent 用户代理
     * @return 本地图片路径
     */
    public static String saveImage(String imageUrl, String cityCode, String userAgent) {
        if (imageUrl == null || imageUrl.trim().isEmpty()) {
            return null;
        }
        
        try {
            // 创建图片保存目录
            File imageDir = new File(IMAGE_PATH);
            if (!imageDir.exists()) {
                imageDir.mkdirs();
            }
            
            // 从URL中提取文件名
            String fileName = extractFileName(imageUrl);
            if (fileName == null) {
                return null;
            }
            
            // 下载图片
            byte[] imageData = HttpUtils.downloadImage(imageUrl, userAgent, "https://" + cityCode + ".lianjia.com/ershoufang/");
            if (imageData == null) {
                return null;
            }
            
            // 保存图片
            Path imagePath = Paths.get(IMAGE_PATH, fileName);
            Files.write(imagePath, imageData);
            
            return imagePath.toAbsolutePath().toString();
        } catch (IOException e) {
            logger.error("保存图片失败: {}", imageUrl, e);
            return null;
        }
    }
    
    /**
     * 从URL中提取文件名
     *
     * @param url 图片URL
     * @return 文件名
     */
    private static String extractFileName(String url) {
        // 使用正则表达式从URL中提取文件名
        java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("https://image1\\.ljcdn\\.com/110000-inspection/(.+?)\\.(\\d+)x(\\d+)\\.jpg$");
        java.util.regex.Matcher matcher = pattern.matcher(url);
        if (matcher.find()) {
            return matcher.group(1) + ".jpg";
        }
        return null;
    }
    
    /**
     * 保存房屋信息列表到JSON和CSV文件
     *
     * @param infoList 房屋信息列表
     * @param cityName 城市名称
     * @param left 起始页码
     * @param right 结束页码
     */
    public static void saveResults(List<HouseInfo> infoList, String cityName, int left, int right) {
        if (infoList == null || infoList.isEmpty()) {
            logger.warn("房屋信息列表为空，无法保存");
            return;
        }
        
        try {
            // 创建信息保存目录
            File infoDir = new File(INFORMATION_PATH);
            if (!infoDir.exists()) {
                infoDir.mkdirs();
            }
            
            // 保存为JSON文件
            saveToJson(infoList, cityName, left, right);
            
            // 保存为CSV文件
            saveToCsv(infoList, cityName, left, right);
            
        } catch (IOException e) {
            logger.error("保存结果失败", e);
        }
    }
    
    /**
     * 保存房屋信息列表到JSON文件
     *
     * @param infoList 房屋信息列表
     * @param cityName 城市名称
     * @param left 起始页码
     * @param right 结束页码
     * @throws IOException IO异常
     */
    private static void saveToJson(List<HouseInfo> infoList, String cityName, int left, int right) throws IOException {
        logger.info("保存到JSON文件...");
        String fileName = String.format("%s_%d-%d.json", cityName, left, right);
        Path jsonPath = Paths.get(INFORMATION_PATH, fileName);
        
        objectMapper.writerWithDefaultPrettyPrinter().writeValue(jsonPath.toFile(), infoList);
        logger.info("JSON文件已保存: {}", jsonPath.toAbsolutePath());
    }
    
    /**
     * 保存房屋信息列表到CSV文件
     *
     * @param infoList 房屋信息列表
     * @param cityName 城市名称
     * @param left 起始页码
     * @param right 结束页码
     * @throws IOException IO异常
     */
    private static void saveToCsv(List<HouseInfo> infoList, String cityName, int left, int right) throws IOException {
        logger.info("保存到CSV文件...");
        String fileName = String.format("%s_%d-%d.csv", cityName, left, right);
        Path csvPath = Paths.get(INFORMATION_PATH, fileName);
        
        // CSV表头
        String[] headers = {"标题", "地址", "户型", "面积", "朝向", "装修情况", "层数", "建造时间", "楼型", "总价", "每平米单价", "图片", "详情链接"};
        
        // 准备CSV数据
        List<String[]> csvData = new ArrayList<>();
        csvData.add(headers);
        
        for (HouseInfo info : infoList) {
            String[] row = new String[headers.length];
            
            // 设置标题和地址
            row[0] = info.getTitle();
            row[1] = info.getLocation();
            
            // 设置详细信息
            Map<String, String> details = info.getDetails();
            if (details != null) {
                row[2] = details.get("configuration");  // 户型
                row[3] = details.get("area");           // 面积
                row[4] = details.get("towards");        // 朝向
                row[5] = details.get("decorate");       // 装修情况
                row[6] = details.get("storey");         // 层数
                row[7] = details.get("period");         // 建造时间
                row[8] = details.get("categorie");      // 楼型
            }
            
            // 设置价格信息
            if (info.getPrice() != null) {
                row[9] = info.getPrice().getTotalPrice();  // 总价
                row[10] = info.getPrice().getUnitPrice();  // 单价
            }
            
            // 设置图片和链接
            row[11] = info.getImage();  // 图片
            row[12] = info.getLink();   // 链接
            
            // 过滤非GBK字符
            for (int i = 0; i < row.length; i++) {
                if (row[i] != null) {
                    row[i] = filterNonGBK(row[i]);
                }
            }
            
            csvData.add(row);
        }
        
        // 写入CSV文件（使用GBK编码以兼容Windows中文环境）
        try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(csvPath.toFile()), Charset.forName("GBK"));
             CSVPrinter csvPrinter = new CSVPrinter(writer, CSVFormat.DEFAULT)) {
            
            for (String[] row : csvData) {
                csvPrinter.printRecord((Object[]) row);
            }
            csvPrinter.flush();
        }
        
        logger.info("CSV文件已保存: {}", csvPath.toAbsolutePath());
    }
    
    /**
     * 过滤非GBK编码字符
     *
     * @param input 输入字符串
     * @return 过滤后的字符串
     */
    private static String filterNonGBK(String input) {
        if (input == null) {
            return null;
        }
        
        StringBuilder result = new StringBuilder();
        for (char c : input.toCharArray()) {
            try {
                String charStr = String.valueOf(c);
                byte[] bytes = charStr.getBytes("GBK");
                result.append(charStr);
            } catch (Exception e) {
                // 忽略非GBK字符
            }
        }
        
        return result.toString();
    }
} 